package com.free4inno.knowledgems.controller;

import com.free4inno.knowledgems.dao.*;
import com.free4inno.knowledgems.domain.*;
import com.free4inno.knowledgems.utils.LogUtils;
import com.free4inno.knowledgems.service.ResourceEsService;
import com.free4inno.knowledgems.service.ResourceService;
import com.free4inno.knowledgems.utils.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;

import static com.free4inno.knowledgems.utils.CompleteUriUtils.getCompleteUri;

/**
 * Author HUYUZHU.
 * Date 2020/9/25 13:12.
 */

@Slf4j
@Controller
@RequestMapping("/resource")
public class ResourceController {

    @Autowired
    private ResourceDAO resourceDao;

    @Autowired
    private UserDAO userDao;

    @Autowired
    private CommentDAO commentDao;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private SpecResourceDAO specResourceDao;

    @Autowired
    private ResourceEsService esService;

    @Autowired
    private SystemManageDAO systemManageDao;

    @Autowired
    private LabelInfoDAO labelInfoDao;

    @Autowired
    private ImageUtils imageUtils;

    @Autowired
    private WriteEsResourceHttpUtils writeEsResourceHttpUtils;

    @RequestMapping("/resource")
    public String resource(@RequestParam(value = "id", required = true) int id,
                           @RequestParam(value = "isBook", required = false) boolean isBook,
                           HttpSession session, HttpServletRequest request, HttpServletResponse httpServletResponse, Map param) {
        log.info(LogUtils.parse("打开资源", "资源id: " + id));

        Resource resource = resourceDao.findAllById(id);
        //取用户名
        User user = new User();
        user.setRealName(Constants.USERNAME);
        user = userDao.findById(resource.getUserId()).orElse(user);
        //取群组名
        resource.setGroupName(resourceService.getGroupName(resource));
        //取标签名
        resource.setLabelName(resourceService.getLabelName(resource));
        //取资源的推荐情况
        resourceService.setRecommendResource(resource);
        //取资源的公告情况
        resourceService.setAnnouncementResource(resource);
        // （此处的保存是为了保存未同步的资源推荐与公告情况）
        resourceDao.save(resource);

        // get book label id
        String bookLabelId = systemManageDao.findAllByVariable("book_label").get().getValue();
        LabelInfo labelInfo = labelInfoDao.findAllById(Integer.parseInt(bookLabelId));
        String bookLabelName = "未知";
        if (labelInfo != null) {
            bookLabelName = labelInfo.getLabelName();
        }

        //取资源的附件
        String attachment = resourceService.getAttachmentJson(id);
        param.put("attachment", attachment);
        //获取这个资源的uri
        String completeUri = getCompleteUri(request);
        session.setAttribute(Constants.COMPLETE_URI, completeUri);
        //判断是否为公开资源
        Boolean isPublic;
        Boolean isInGroup;
        if (resource.getPermissionId() == 0) {
            /* 非公开资源 */
            isPublic = false;
            log.info(LogUtils.parse("打开资源", "当前资源为非公开资源"));
            // 判断是否登录
            if (session.getAttribute(Constants.ACCOUNT) == null) {
                log.warn(LogUtils.parse("打开资源", "当前资源为非公开资源且未登录，跳转登录页面"));
                try {
                    httpServletResponse.sendRedirect("/login");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return "/login/login";
            } else {
                // 判断用户是否在资源群组内
                isInGroup = resourceService.isInResourceGroup(resource, (int) session.getAttribute(Constants.USER_ID));
            }
        } else {
            /* 公开资源 */
            isPublic = true;
            isInGroup = true;
            log.info(LogUtils.parse("打开资源", "当前资源为公开资源"));
        }

        param.put("resource", resource);
        param.put("user", user);
        param.put("bookLabelName", bookLabelName);

        //判断用户是否有权限打开
        if (!isPublic && !isInGroup) {
            log.warn(LogUtils.parse("打开资源", "当前资源为非公开资源，且用户不在群组内，跳转reject页面"));
            return "/resource/rejectResource";
        }
        //判断是否书籍
        if (isBook) {
            log.info(LogUtils.parse("打开资源", "打开书籍资源，转到页面"));
            return "/resource/bookResource";
        }
        log.info(LogUtils.parse("打开资源", "打开普通资源，转到页面"));
        return "/resource/resource";
    }

    @ResponseBody
    @PostMapping("/changePermission")
    public String changePermission(@RequestParam("id") int id, HttpSession session) {
        log.info(LogUtils.parse("修改资源权限", "资源id: " + id));

        String result = "";
        Resource resource = resourceDao.findResourceById(id);
        //反转resource.permissionId的值
        if (resource.getPermissionId() == 0) {
            resource.setPermissionId(1);
            result = "permissionId=1";
        } else {
            resource.setPermissionId(0);
            result = "permissionId=0";
        }
        resourceDao.save(resource);
        esService.updateResourceES(id);

        log.info(LogUtils.parse("修改资源权限", "返回反转后的当前资源权限类型, " + result));
        return result;
    }

    @RequestMapping("/deleteResource")
    public String deleteResource(@RequestParam("id") int id, HttpSession session) {
        log.info(LogUtils.parse("删除资源", "资源id: " + id));
        //删除正文中图片
        Resource resource = resourceDao.findResourceById(id);
        String text = resource.getText();
        List<String> imageSrc = imageUtils.getImgSrc(text);
        String result = "";
        for (String src : imageSrc) {
            result = imageUtils.deleteImage(src);
        }
        //删除resource表里的一条数据
        resourceDao.deleteById(id);
        //删除ES索引中的一条数据
        esService.deleteResourceES(id);
        //删除spec表里的一条数据
        if (specResourceDao.findByResourceId(id) != null) {
            specResourceDao.deleteByResourceId(id);
        }
        //删除评论
        if (commentDao.findByResourceId(id) != null && commentDao.findByResourceId(id).size() != 0) {
            commentDao.deleteAllByResourceId(id);
        }
        log.info(LogUtils.parse("删除资源", "删除成功"));
        return "redirect:/";
    }

    @RequestMapping("/getComment")
    public String getComment(@RequestParam("resourceId") int resourceId,
                             @RequestParam("page") int page,
                             Map param, HttpSession session) {
        log.info(LogUtils.parse("获取资源评论", "resourceId: " + resourceId + ", page: " + page));
        int pageSize = 5;
        Sort sort = Sort.by(Sort.Direction.ASC, "time");
        Pageable pageable = PageRequest.of(page, pageSize, sort);
        Page<Comment> commentPage = commentDao.findAllByResourceId(resourceId, pageable);
        List<Comment> commentList = commentPage.getContent();
        int pageTotal = commentPage.getTotalPages();
        long commentTotal = commentPage.getTotalElements();

        // List<Comment> commentList = commentDao.findByResourceId(resourceId);
        for (Comment comment : commentList) {
            String userName = userDao.findById(comment.getUserId()).get().getRealName();
            comment.setUserName(userName);
            int picID = (int) userName.charAt(1) % 20;
            String picName = picID + ".png";
            comment.setPicName(picName);
        }
        param.put("commentList", commentList);
        param.put("pageTotal", pageTotal);
        param.put("commentTotal", commentTotal);
        param.put("resourceId", resourceId);
        if (session.getAttribute(Constants.USER_ID) == null) {
            param.put("userId", "");
            param.put("userName", "");
            session.setAttribute("login_flag", 0);
        } else {
            param.put("userId", session.getAttribute(Constants.USER_ID));
            param.put("userName", userDao.findById((int) session.getAttribute(Constants.USER_ID)).get().getRealName());
        }
        log.info(LogUtils.parse("获取资源评论", "返回_comment子页"));
        return "resource/_comment";
    }

    @ResponseBody
    @RequestMapping("/newComment")
    public String newComment(@RequestParam("content") String content,
                             @RequestParam("resourceId") int resourceId, HttpSession session, HttpServletRequest request) throws Exception {
        log.info(LogUtils.parse("新增评论", "resourceId: " + resourceId));
        String contentHtml = "<p class=\"mb-0\">" + StringUtils.inputStringFormat(content).replaceAll("<br/>", "</p><p class=\"mb-0\">") + "</p>";
        contentHtml = imageUtils.DownloadExternalImage(contentHtml, session); //调用ImageUtils下载外链图片的方法
        Comment comment = new Comment();
        comment.setUserId((int) session.getAttribute(Constants.USER_ID));
        comment.setTime(new Timestamp(new Date().getTime()));
        comment.setContent(contentHtml);
        comment.setResourceId(resourceId);
        commentDao.save(comment);
        String result = "ok";

        Resource resource = resourceDao.findResourceById(resourceId);
        ResourceES resourceES = new ResourceES();
        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                writeEsResourceHttpUtils.writeResourceToESHTTP(resource, resourceES);
            }
        }).start();
        log.info(LogUtils.parse("新增评论", "评论添加成功"));
        return result;
    }

    @ResponseBody
    @RequestMapping("/deleteComment")
    public String deleteComment(@RequestParam("commentId") int commentId, HttpSession session) {
        log.info(LogUtils.parse("删除评论", "评论Id: " + commentId));
        commentDao.deleteById(commentId);
        String result = "ok";
        log.info(LogUtils.parse("删除评论", "删除成功"));
        return result;
    }
}
